Blocks 布局
Blocks 是 Gradio 中的高级 API,它提供了比 Interface 更灵活的布局选项和更强大的交互能力。使用 Blocks,您可以创建复杂的多步骤应用,自定义组件的布局,并设置复杂的事件处理。
基本用法
Blocks 的基本用法如下:
python
import gradio as gr
with gr.Blocks() as demo:
gr.Markdown("# 我的应用")
with gr.Row():
with gr.Column():
input1 = gr.Textbox(label="输入1")
input2 = gr.Number(label="输入2")
button = gr.Button("提交")
with gr.Column():
output = gr.Textbox(label="结果")
button.click(fn=process_inputs, inputs=[input1, input2], outputs=output)
demo.launch()
与 Interface 不同,Blocks 使用上下文管理器(with
语句)来定义界面结构,并允许您精确控制组件的布局和交互。
布局元素
Blocks 提供了多种布局元素来组织您的界面:
Row 和 Column
Row
和 Column
允许您创建水平和垂直排列的组件:
python
with gr.Blocks() as demo:
with gr.Row(): # 水平排列
text1 = gr.Textbox(label="左侧文本")
text2 = gr.Textbox(label="右侧文本")
with gr.Column(): # 垂直排列
text3 = gr.Textbox(label="上方文本")
text4 = gr.Textbox(label="下方文本")
Group
Group
允许您将相关组件分组在一起,并添加一个标题:
python
with gr.Blocks() as demo:
with gr.Group():
gr.Markdown("## 用户信息")
name = gr.Textbox(label="姓名")
age = gr.Number(label="年龄")
Tab
Tab
允许您创建标签页界面:
python
with gr.Blocks() as demo:
with gr.Tabs():
with gr.Tab("第一个标签"):
gr.Markdown("这是第一个标签的内容")
input1 = gr.Textbox(label="标签1输入")
with gr.Tab("第二个标签"):
gr.Markdown("这是第二个标签的内容")
input2 = gr.Textbox(label="标签2输入")
Box (Accordion) 折叠面板
Accordion
允许您创建可折叠的面板:
python
with gr.Blocks() as demo:
with gr.Accordion("点击展开高级选项"):
option1 = gr.Checkbox(label="选项1")
option2 = gr.Checkbox(label="选项2")
事件处理
Blocks 的一个主要优势是其灵活的事件处理系统。您可以定义组件之间的复杂交互,例如在用户与一个组件交互时更新另一个组件。
基本事件处理
最常见的事件是按钮点击:
python
def greet(name):
return f"你好,{name}!"
with gr.Blocks() as demo:
name_input = gr.Textbox(label="您的名字")
greet_btn = gr.Button("问候")
output = gr.Textbox(label="问候语")
greet_btn.click(fn=greet, inputs=name_input, outputs=output)
多个事件源和目标
您可以连接多个输入和输出:
python
def full_name(first_name, last_name):
return f"{last_name}{first_name}"
with gr.Blocks() as demo:
first_name = gr.Textbox(label="名")
last_name = gr.Textbox(label="姓")
btn = gr.Button("生成全名")
result = gr.Textbox(label="全名")
btn.click(fn=full_name, inputs=[first_name, last_name], outputs=result)
事件类型
除了 click
外,不同组件还支持其他事件类型:
python
# 输入变化时触发
textbox.change(fn=function, inputs=[...], outputs=[...])
# 组件获得焦点时触发
textbox.focus(fn=function, inputs=[...], outputs=[...])
# 组件失去焦点时触发
textbox.blur(fn=function, inputs=[...], outputs=[...])
# 提交时触发 (按回车键)
textbox.submit(fn=function, inputs=[...], outputs=[...])
使用 update 函数动态修改组件
Gradio 提供了 update
函数来动态更改组件属性:
python
def update_dropdown(choice):
if choice == "水果":
return gr.Dropdown.update(choices=["苹果", "香蕉", "橙子"])
else:
return gr.Dropdown.update(choices=["黄瓜", "茄子", "西红柿"])
with gr.Blocks() as demo:
category = gr.Radio(["水果", "蔬菜"], label="类别")
items = gr.Dropdown(label="物品")
category.change(fn=update_dropdown, inputs=category, outputs=items)
状态管理
使用 State 组件保存状态
State 组件允许您在会话中存储不显示在界面上的数据:
python
def add_to_history(message, history):
history = history + [(message, f"回复: {message}")]
return "", history # 清空输入框,更新历史记录
with gr.Blocks() as demo:
chatbot = gr.Chatbot(label="聊天历史")
msg = gr.Textbox(label="消息")
chat_history = gr.State([]) # 状态变量,不显示在界面上
msg.submit(fn=add_to_history, inputs=[msg, chat_history], outputs=[msg, chatbot])
高级用法
预处理和后处理函数
您可以添加多个函数串联处理:
python
def preprocess(text):
return text.lower()
def process(text):
return text.upper()
def postprocess(text):
return f"处理结果: {text}"
with gr.Blocks() as demo:
text_in = gr.Textbox(label="输入")
btn = gr.Button("处理")
text_out = gr.Textbox(label="输出")
btn.click(fn=preprocess, inputs=text_in, outputs=gr.Textbox()).then(
fn=process, outputs=gr.Textbox()).then(
fn=postprocess, outputs=text_out)
自定义 JavaScript 交互
您可以添加自定义 JavaScript 函数处理交互:
python
with gr.Blocks() as demo:
text = gr.Textbox()
btn = gr.Button("转换")
output = gr.Textbox()
btn.click(
fn=None, # 没有 Python 函数
inputs=text,
outputs=output,
_js="""
function(text) {
return text.toUpperCase();
}
"""
)
动态添加和删除组件
Blocks API 还允许动态添加和删除组件:
python
def create_textbox():
return gr.Textbox(label="新文本框", interactive=True)
with gr.Blocks() as demo:
with gr.Column() as col:
text = gr.Textbox(label="已有文本框")
add_btn = gr.Button("添加新文本框")
add_btn.click(fn=create_textbox, inputs=None, outputs=col)
示例应用
交互式图像处理应用
python
import gradio as gr
import numpy as np
from PIL import Image, ImageEnhance, ImageFilter
def adjust_image(image, brightness, contrast, blur):
img = Image.fromarray(image)
# 调整亮度
if brightness != 1:
enhancer = ImageEnhance.Brightness(img)
img = enhancer.enhance(brightness)
# 调整对比度
if contrast != 1:
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(contrast)
# 应用模糊
if blur > 0:
img = img.filter(ImageFilter.GaussianBlur(radius=blur))
return np.array(img)
with gr.Blocks() as demo:
gr.Markdown("# 图像编辑器")
with gr.Row():
with gr.Column():
input_image = gr.Image(label="原始图像")
with gr.Row():
brightness = gr.Slider(0.5, 2.0, value=1, label="亮度")
contrast = gr.Slider(0.5, 2.0, value=1, label="对比度")
blur = gr.Slider(0, 10, value=0, label="模糊")
process_btn = gr.Button("处理")
with gr.Column():
output_image = gr.Image(label="处理后图像")
process_btn.click(
fn=adjust_image,
inputs=[input_image, brightness, contrast, blur],
outputs=output_image
)
# 实时处理
input_image.change(
fn=adjust_image,
inputs=[input_image, brightness, contrast, blur],
outputs=output_image
)
brightness.change(
fn=adjust_image,
inputs=[input_image, brightness, contrast, blur],
outputs=output_image
)
contrast.change(
fn=adjust_image,
inputs=[input_image, brightness, contrast, blur],
outputs=output_image
)
blur.change(
fn=adjust_image,
inputs=[input_image, brightness, contrast, blur],
outputs=output_image
)
demo.launch()
多步骤表单应用
python
import gradio as gr
def validate_step1(name, email):
if not name:
return gr.update(visible=True), gr.update(visible=False, value=None)
if "@" not in email:
return gr.update(visible=True), gr.update(visible=False, value=None)
return gr.update(visible=False), gr.update(visible=True)
def submit_form(name, email, age, feedback):
return f"表单已提交!\n姓名: {name}\n邮箱: {email}\n年龄: {age}\n反馈: {feedback}"
with gr.Blocks() as demo:
gr.Markdown("# 多步骤表单")
name = gr.Textbox(label="姓名")
email = gr.Textbox(label="邮箱")
next_btn = gr.Button("下一步")
error_box = gr.Markdown(visible=False, value="请填写所有必填字段!")
with gr.Group(visible=False) as step2:
age = gr.Number(label="年龄")
feedback = gr.Textbox(label="反馈", lines=3)
submit_btn = gr.Button("提交")
result = gr.Textbox(label="结果", visible=False)
next_btn.click(
fn=validate_step1,
inputs=[name, email],
outputs=[error_box, step2]
)
submit_btn.click(
fn=submit_form,
inputs=[name, email, age, feedback],
outputs=result
)
demo.launch()
总结
Blocks API 提供了比 Interface 更灵活的方式来构建 Gradio 应用。它允许您:
- 精确控制组件的布局和排列
- 创建复杂的事件处理和组件交互
- 设计多步骤的应用流程
- 管理状态和数据流
- 自定义前端行为和外观
虽然 Blocks 比 Interface 更复杂,但它提供了更大的灵活性,使您能够构建功能丰富的应用,如对话机器人、多步骤表单、交互式仪表板等。
在下一章中,我们将介绍 ChatInterface,这是一个专门为构建聊天应用而设计的高级接口。